﻿using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using StockholmsStad.Business;
using StockholmsStad.Runtime.Serialization.DataContract;
using StockholmsStad.Runtime.Serialization.DataContract.Enums;
using StockholmsStad.ServiceModel.Interfaces;
using StockholmsStad.Utilities.Exceptions;

namespace StockholmsStad.ServiceModel.Services
{
    /// <summary>
    /// 
    /// </summary>
    public class TicketService : ITicketService
    {
        /// <summary>
        /// Implementation av operationskontrakt som hämtar alla ärenden
        /// </summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        /// <param name="partOfName"></param>
        /// <param name="partOfBirthday"></param>
        /// <param name="ticketStatus">Anger status på de ärenden som ska hämtas. </param>
        /// <returns>En lista av typen <see cref="Ticket"/> eller en tom lista om inga ärenden finns.</returns>
        public IList<CouplesSummaryItem> GetTickets(User user, string partOfName, string partOfBirthday, TicketStatusType ticketStatus)
        {
            try
            {
                return new TicketBusiness(user).GetTickets(partOfName, partOfBirthday, ticketStatus).ToList();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="ticketId"></param>
        /// <returns></returns>
        public Couple GetCouple(User user, int ticketId)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                return ticketBusiness.GetCouple(ticketId);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

        ///<summary>
        /// Skickar ett mail till användaren med det befintliga lösenordet
        ///</summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        ///<param name="parvisUser">Epostadressen till den användare som lösenordet ska skickas till. </param>
        public void SendForgottenPassword(User user, ParvisUser parvisUser)
        {
            try
            {
                var userBusiness = new UserBusiness(user);
                userBusiness.SendForgottenPasswordMail(parvisUser);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

        /// <summary>
        /// Implementation av operationskontrakt för addering av nya ärenden.
        /// </summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        /// <param name="couple">Paret (<see cref="Couple"/>) som ska läggas till ärendet.</param>
        /// <param name="ceremonyInformation">Ceremoniinformationen (<see cref="Ceremony"/>) som ska läggas till ärendet.</param>
        /// <returns>Ärendeid-numret.</returns>
        public int AddTicket(User user, Couple couple, Ceremony ceremonyInformation)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                return ticketBusiness.CreateTicket(couple, ceremonyInformation);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

        /// <summary>
        /// Operationskontrakt för modifiering av befintlig förrättare
        /// </summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        /// <param name="ticketId">Ärendeid-numret</param>
        /// <param name="couple">Paret (<see cref="Couple"/>) som ska uppdateras.</param>
        public void UpdateCouple(User user, int ticketId, Couple couple)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                ticketBusiness.UpdateCouple(ticketId, couple);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

        /// <summary>
        /// Implementation av operationskontrakt för modifering av befintligt ärenden.
        /// </summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        /// <param name="ticketId">Ärendeid-numret</param>
        /// <param name="couple">Paret (<see cref="Couple"/>) som ska läggas till ärendet.</param>
        /// <param name="ceremonyInformation">Ceremoniinformationen (<see cref="Ceremony"/>) som ska läggas till ärendet.</param>
        public void UpdateTicket(User user, int ticketId, Couple couple, Ceremony ceremonyInformation)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                ticketBusiness.UpdateTicket(couple, ceremonyInformation, ticketId);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

        /// <summary>
        /// Uppdaterar TicketStatus för en lista med Tickets
        /// </summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        /// <param name="ceremonies">Ceremoniinformationen (<see cref="CeremonySummaryDetails"/>) som ska läggas till ärendet.</param>
        public void UpdateTicketsWithStatus(User user, List<CeremonySummaryDetails> ceremonies)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                ticketBusiness.UpdateTicketsWithStatus(ceremonies);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public List<History> GetNotices(User user)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                return ticketBusiness.GetNotices();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.ErrorMessage));
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="historyId"></param>
        public void InactivateNotice(User user, int historyId)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                ticketBusiness.InactivateNotice(historyId);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

        /// <summary>
        /// Hämtar datum då inga ordinarie bokningar kan bokas (för kalender som 
        /// endast tar "utblockade" datum). 
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public List<DateRange> GetNonAvailableDates(User user)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                return ticketBusiness.GetNonAvailableDates();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(
                    new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

        /// <summary>
        /// Hämtar icke fullbokade tidsblock som en lista med start-slut-datum (för kalender som 
        /// endast tar "utblockade" datum. 
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public List<DateRange> GetNonFullyBookedDates(User user)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                return ticketBusiness.GetNonFullyBookedDates();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode,
                                                                                                          e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(
                    new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

        /// <summary>
        /// Hämtar övrig information för ett ärende. 
        /// </summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        /// <param name="ticketId">Ärende-numret för den ceremoniinformation som ska hämtas</param>
        /// <returns>Informationen för ett visst ärende (<see cref="TicketInformation"/>). </returns>
        public TicketInformation GetTicketInformation(User user, int ticketId)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                return ticketBusiness.GetTicketInformation(ticketId);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

        /// <summary>
        /// Lägger till övrig information till ett ärende. 
        /// </summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        /// <param name="ticketInformation">Den information som ska läggas till (<see cref="TicketInformation"/>).</param>
        /// <returns>Id-värdet på den tillagda informationen. </returns>
        public int AddTicketInformation(User user, TicketInformation ticketInformation)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                return ticketBusiness.AddTicketInformation(ticketInformation);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

        /// <summary>
        /// Uppdaterar övrig information för ett visst ärende. 
        /// </summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        /// <param name="ticketInformation">Den information som ska uppdateras. </param>
        public void UpdateTicketInformation(User user, TicketInformation ticketInformation)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                ticketBusiness.UpdateTicketInformation(ticketInformation);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<StockholmStadSystemErrorFault>(new StockholmStadSystemErrorFault(e.ErrorCode, e.Message));
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<StockholmStadApplicationErrorFault>(new StockholmStadApplicationErrorFault(e.ErrorCode, e.Message));
            }
        }

    }
}
